package de.slothsoft.wasbinich.android;

import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import de.slothsoft.wasbinich.android.control.CountDown;
import de.slothsoft.wasbinich.android.control.TextViewCountDown;
import de.slothsoft.wasbinich.android.util.ImageUtil;
import de.slothsoft.wasbinich.android.util.StyleUtil;
import de.slothsoft.wasbinich.android.util.ViewUtil;
import de.slothsoft.wasbinich.core.GameResult;
import de.slothsoft.wasbinich.core.Picture;
import de.slothsoft.wasbinich.core.WasBinIch;
import de.slothsoft.wasbinich.core.database.Database;
import de.slothsoft.wasbinich.core.util.PictureUtil;

public class QuestionActivity extends AbstractActivity implements OnEditorActionListener {

    private static final String ARG_PICTURE = "picture"; //$NON-NLS-1$
    private static final String ARG_TIMER = "timer"; //$NON-NLS-1$
    private static final String ARG_RESULT = "result"; //$NON-NLS-1$

    private static final int TIME_SECOND = 1000;

    public static class CallBack {

	public void onPictureFetched(QuestionActivity questionActivity, int pictureIndex) {
	    // nothing to do on default
	}
    }

    public static CallBack QUESTION_CALL_BACK = new CallBack();

    private Picture picture;
    private Bitmap bitmap;

    private GameResult result;
    private CountDown countDown;
    private int countDownPaused;
    private int pictureIndex;

    private boolean timerIsAboutToStart;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);

	requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

	setContentView(R.layout.activity_question);
	getEditText().setOnEditorActionListener(this);
	StyleUtil.styleChronometer(this, getChronometer());

	this.timerIsAboutToStart = false;
	if (savedInstanceState != null && savedInstanceState.containsKey(ARG_PICTURE)
		&& savedInstanceState.containsKey(ARG_TIMER) && savedInstanceState.containsKey(ARG_RESULT)) {
	    initTimer(savedInstanceState.getInt(ARG_TIMER));
	    setExistingPicture((Picture) savedInstanceState.get(ARG_PICTURE));
	    this.result = (GameResult) savedInstanceState.get(ARG_RESULT);
	    this.timerIsAboutToStart = true;
	} else if (this.picture == null) {
	    this.result = new GameResult();
	    initTimer(WasBinIch.GAME_LENGTH_IN_SECONDS * TIME_SECOND);
	    fetchPicture();
	    this.timerIsAboutToStart = true;
	}
    }

    @Override
    protected void onResume() {
	super.onResume();
	if (!this.timerIsAboutToStart) {
	    startCountDown();
	}
    }

    private void initTimer(int miliSecondsInFuture) {
	this.countDownPaused = 0;
	this.countDown = new TextViewCountDown(getChronometer(), miliSecondsInFuture, TIME_SECOND) {

	    private static final long serialVersionUID = 7319207527852965113L;

	    @Override
	    public void onFinish() {
		super.onFinish();
		performTimeIsUp();
	    }
	};
    }

    protected void performTimeIsUp() {
	Intent resultIntent = new Intent(this, ResultActivity.class);
	resultIntent.putExtra(ResultActivity.ARG_RESULT, this.result);
	startActivityForResult(resultIntent, ActionCodes.SHOW_RESULT);
    }

    private void fetchPicture() {
	QUESTION_CALL_BACK.onPictureFetched(this, this.pictureIndex++);
	clearActivity();

	ViewUtil.setText(findViewById(R.id.question_answer), ""); //$NON-NLS-1$
	new Thread(new Runnable() {
	    @Override
	    public void run() {
		try {
		    final Picture picture = Database.getInstance().getPictureBean().getRandomPicture();
		    final Bitmap bitmap = ImageUtil.createSectionBitmap(picture);
		    getWindow().getDecorView().post(new Runnable() {
			@Override
			public void run() {
			    startNewPicture(picture, bitmap);
			}
		    });
		} catch (Exception exception) {
		    handleFatalException(exception);
		}
	    }
	}).start();
    }

    protected void clearActivity() {
	stopCountDown();
	getImageView().setImageBitmap(null);
	getEditText().setVisibility(View.INVISIBLE);
	setProgressBarIndeterminateVisibility(true);
    }

    protected void startNewPicture(Picture picture, Bitmap bitmap) {
	disposeBitmap();
	this.picture = picture;
	this.bitmap = bitmap;
	setProgressBarIndeterminateVisibility(false);
	getImageView().setImageBitmap(this.bitmap);
	getEditText().setVisibility(View.VISIBLE);
	startCountDown();
    }

    protected void setExistingPicture(Picture picture) {
	disposeBitmap();
	this.picture = picture;
	this.bitmap = picture == null ? null : ImageUtil.createSectionBitmap(picture);
	getImageView().setImageBitmap(this.bitmap);
	startCountDown();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
	super.onSaveInstanceState(outState);
	if (this.picture != null) {
	    outState.putSerializable(ARG_PICTURE, this.picture);
	}
	if (this.countDown != null) {
	    outState.putInt(ARG_TIMER, (int) this.countDown.getMilliSecondsUntilFinished());
	}
	if (this.result != null) {
	    outState.putSerializable(ARG_RESULT, this.result);
	}
    }

    @Override
    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
	updateGameResult(view.getText());
	pauseCountDown();
	Intent answerIntend = new Intent(this, AnswerActivity.class);
	answerIntend.putExtra(AnswerActivity.ARG_ANSWER, view.getText());
	answerIntend.putExtra(AnswerActivity.ARG_PICTURE, this.picture);
	startActivityForResult(answerIntend, ActionCodes.SHOW_ANSWER);
	return true;
    }

    private void updateGameResult(CharSequence answer) {
	if (PictureUtil.isCorrectAnswer(this.picture, answer.toString())) {
	    this.result.addCorrectAnswer();
	} else {
	    this.result.addWrongAnswer();
	}
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
	super.onActivityResult(requestCode, resultCode, data);
	if (requestCode == ActionCodes.SHOW_ANSWER && resultCode == RESULT_OK) {
	    fetchPicture();
	}
    }

    @Override
    public void onPause() {
	pauseCountDown();
	super.onPause();
    }

    @Override
    public void onDestroy() {
	disposeBitmap();
	stopCountDown();
	super.onDestroy();
    }

    private void disposeBitmap() {
	if (this.bitmap != null) {
	    this.bitmap.recycle();
	    this.bitmap = null;
	}
    }

    public void pauseCountDown() {
	this.countDown.pause();
	this.countDownPaused++;
	Log.d("slothsoft", "Pausing count down for the " + this.countDownPaused + ". time"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    }

    public void startCountDown() {
	this.timerIsAboutToStart = false;
	this.countDownPaused--;
	if (this.countDownPaused <= 0) {
	    // all that have paused have started this countdown
	    this.countDown.start();
	    this.countDownPaused = 0;
	    Log.d("slothsoft", "Starting count down!"); //$NON-NLS-1$ //$NON-NLS-2$
	} else {
	    Log.d("slothsoft", "Time till count down starts: " + this.countDownPaused); //$NON-NLS-1$//$NON-NLS-2$
	}
    }

    public void stopCountDown() {
	this.countDown.pause();
	this.countDownPaused = 0;
	Log.d("slothsoft", "Stopping count down"); //$NON-NLS-1$ //$NON-NLS-2$
    }

    @Override
    public void onBackPressed() {
	NavUtils.navigateUpFromSameTask(this);
    }

    protected ImageView getImageView() {
	return (ImageView) findViewById(R.id.question_imageSection);
    }

    protected EditText getEditText() {
	return (EditText) findViewById(R.id.question_answer);
    }

    protected TextView getChronometer() {
	return (TextView) findViewById(R.id.question_chronometer);
    }
}
